package base.jdk8_demo.date;

import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;


/**
 * https://yourbatman.cn/x2y/4fe7fafa.html
 */
public class Demo02 {
    /**
     * jdk7及以下通过 Calendar操作时间
     *
     * @date 2020年7月15日 下午16:05:05
     * Calendar实例如果没有通过setTime()指定某个时间,默认就是当前时间. <br>
     */
    @Test
    public void calendarTest() throws ParseException {
        // 当前时间操作
        Calendar c2 = Calendar.getInstance();
        System.out.println(c2.get(Calendar.YEAR));//2020
        System.out.println(c2.get(Calendar.MONTH));//6,月份要+1才是当前月份
        System.out.println(c2.get(Calendar.DAY_OF_MONTH));//15
        System.out.println(c2.get(Calendar.DAY_OF_YEAR));//197,2020-01-01距离2020-07-15之间有197天
        System.out.println(c2.get(Calendar.HOUR));//4点
        System.out.println(c2.get(Calendar.HOUR_OF_DAY));//16点
        System.out.println(c2.get(Calendar.MINUTE));//5分
        System.out.println(c2.get(Calendar.SECOND));//5秒
        System.out.println(c2.get(Calendar.MILLISECOND));//617毫秒
        // 当前时间:2020-7-15 16:5:5.617
        System.out.println("当前时间:" + c2.get(Calendar.YEAR) + "-" + (c2.get(Calendar.MONTH) + 1) + "-"
                + c2.get(Calendar.DAY_OF_MONTH) + " " + c2.get(Calendar.HOUR_OF_DAY) + ":" + c2.get(Calendar.MINUTE)
                + ":" + c2.get(Calendar.SECOND) + "." + c2.get(Calendar.MILLISECOND));

        // 指定时间操作
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date date = sdf.parse("2019/04/10");
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date);
        System.out.println(c1.get(Calendar.YEAR));// 2019
        System.out.println(c1.get(1));// 2019
    }

    /**
     * 以下是jdk8 提供操作时间的方式
     *
     * @date 2021-4-27 17:26:05
     * 	1、获取今天日期
     * 	2、从日期当中获取年、月、日
     * 	3、 获取指定日期对象
     * 	4、 LocalDate比较是否相等即为比较日期是否为同一天，而不是LocalDate是否为同一个对象。
     * 	5、闰年判断
     */
    @Test
    public void test1() {
        // 获取当天日期的两种方式
        LocalDate today = LocalDate.now();
        System.out.println("今天是:" + today);// 今天是:2021-04-27
        LocalDate today2 = LocalDateTime.now().toLocalDate();
        System.out.println("今天是:"+today2);

        System.out.println(LocalDateTime.now().getYear());//2021
        System.out.println(LocalDateTime.now().getMonthValue());//4
        System.out.println(LocalDateTime.now().getDayOfYear());//117
        System.out.println(LocalDateTime.now().getDayOfMonth());//27
        System.out.println(LocalDateTime.now().getDayOfWeek());//TUESDAY

        System.out.println(LocalDate.now().getYear());
        System.out.println(LocalDate.now().getMonthValue());
        System.out.println(LocalDate.now().getDayOfYear());
        System.out.println(LocalDate.now().getDayOfMonth());
        System.out.println(LocalDate.now().getDayOfWeek());

        // 获取某个特定日期对象
        LocalDate oldDay = LocalDate.of(2021, 3, 27);
        System.out.println("上个月的："+oldDay);

        //检查日期是否相等
        LocalDate targetDay = LocalDate.of(2021, 6, 19);
        System.out.println(targetDay.equals(LocalDate.now()));

        System.out.println("今年是闰年吗？ "+ LocalDate.now().isLeapYear());
    }

    /**
     * YearMonth、MonthDay 使用
     *
     * 	检查是否重复日期，比如每年的客户生日，每月还款日，每年保费日。可以通过MonthDay操作<p>
     * 	类似的，如果想操作年月可以通过，YearMonth类
     * @date 2020-7-15 17:19:05
     * 	1、生日提醒
     * 	2、定期存款到期提醒
     * <br>
     */
    @Test
    public void test2() {
        MonthDay birth = MonthDay.of(4, 27);
        System.out.println(birth);//--04-27

        LocalDate today = LocalDate.now();
        MonthDay currentMonthDay = MonthDay.from(today);

        //比较两个MonthDay对象是否相等，只要对象里面的月、日相等即为对象相等
        if(Objects.equals(birth, currentMonthDay)) {
            System.out.println(birth+" 是你的生日.");
        }else {
            System.out.println("今天是："+currentMonthDay+"，还没到你的生日");
        }

        YearMonth currentYearMonth = YearMonth.now();
        int days = currentYearMonth.lengthOfMonth();
        System.out.println("当前是："+currentYearMonth+ ", 该月有"+days +"天。");

        YearMonth expires = YearMonth.of(2021, 4);
        System.out.println("您的信用卡将在" + expires +"过期。");
    }

    /**
     * 	日期|时间往后推算,plus(num, ChronoUnit.HOURS|YEARS)，实际中使用plusXxx(±number)更为通用,-表示效果同minus(减)
     * @date 2020-07-15 17:45:00.151
     * @Description: LocalTime 来获取当前时间 、LocalDate 来获取当前日期
     * 1. 5秒钟后时间、5分钟后时间、5小时后时间
     * 2. 3天后日期、3周后日期、3个月后日期、3年后日期
     * <br>
     */
    @Test
    public void test3() {
        LocalTime time = LocalTime.now();
        System.out.println("当前时间是:"+time);

        LocalTime nextSecond = time.plus(5, ChronoUnit.SECONDS);
        System.out.println("5秒后是："+nextSecond);
        System.out.println(time.plusSeconds(5));
        LocalTime beforeSecond = time.plus(-5, ChronoUnit.SECONDS);
        System.out.println("5秒前是："+beforeSecond);
        System.out.println(time.plusSeconds(-5));

        LocalTime nextMinutes = time.plus(5, ChronoUnit.MINUTES);
        System.out.println("5分钟后是："+nextMinutes);
        System.out.println(time.plusMinutes(5));

        LocalTime nextHour = time.plusHours(5);
        System.out.println("5小时后是："+nextHour);

        LocalDate today = LocalDate.now();
        System.out.println("两年后的今天是："+today.plusYears(2));
        System.out.println("十天后是："+today.plusDays(10));
        System.out.println("三个月后是："+ today.plusMonths(3));//三个月后是：2020-10-15

        LocalDateTime todayTime = LocalDateTime.now();
        System.out.println("三个月后是："+todayTime.plusMonths(3));//三个月后是：2020-10-15T18:07:47.792
    }

    /**
     * 	日期|时间往前推算，minus(num, ChronoUnit.HOURS|YEARS)，实际中使用minusXxx(±number)更为通用,-表示效果同plus(加)
     * @date 2020-07-16T14:57:10.639
     * 	1、5秒前时间、5分钟前时间、5小时前时间
     * 	2、3天前日期、3月前日期、3年前日期
     * <br>
     */
    @Test
    public void test4() {
        LocalTime time = LocalTime.now();
        LocalTime nextHour = time.minus(2, ChronoUnit.HOURS);
        System.out.println("2小时前是："+nextHour);
        nextHour = time.minusHours(3);
        System.out.println("3小时前是："+nextHour);

        LocalDate time2 = LocalDate.now();
        LocalDate nextDay = time2.minus(2, ChronoUnit.DAYS);
        System.out.println("2天前是："+ nextDay);
        nextDay = time2.minusDays(3);
        System.out.println("3天前是："+nextDay);

        nextDay = time2.minusMonths(2);
        System.out.println("2个月前是："+nextDay);
        nextDay = time2.minusYears(2);
        System.out.println("2年前是："+nextDay);
    }

    /**
     * @Description: 日期、时间前后比较大小
     * <br>
     */
    @Test
    public void test5() {
        //日期前后比较
        LocalDate now = LocalDate.now();
        LocalDate tomorrow = now.plusDays(1);
        LocalDate yesterday = now.minusDays(1);
        System.out.println(tomorrow.isAfter(now));// true
        System.out.println(yesterday.isBefore(now));// true


        //时间前后比较
        LocalTime time = LocalTime.now();
        LocalTime time2 = LocalTime.now();
        System.out.println("time:"+time);
        System.out.println("time2:"+time2);
        System.out.println(time.equals(time2));//true

        LocalTime before = time.minusHours(5);
        LocalTime after = time.plusHours(5);
        System.out.println(before.isBefore(time));// true
        System.out.println(after.isAfter(time));// true
    }

    /**
     * @Description:  时区转换测试
     * <br>
     */
    @Test
    public void test6() {
        //使用UTC时区转换后得到的时区Clock
        Clock clock = Clock.systemUTC();
        System.out.println(clock);//SystemClock[Z]
        //系统默认时区Clock
        Clock clockZone = Clock.systemDefaultZone();
        System.out.println(clockZone);//SystemClock[Asia/Shanghai]

        LocalDate today = LocalDate.now(clock); //如果你需要对不同时区的日期进行处理的话这是相当方便的
        System.out.println(today);//2020-04-20
        LocalDate eventDate = LocalDate.of(2020, 3, 20);
        System.out.println(eventDate.isBefore(today));//true


        LocalDateTime localDateAndTime = LocalDateTime.now();
        System.out.println(localDateAndTime);//2020-04-20T09:25:27.723
        ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localDateAndTime, ZoneId.of("America/New_York"));
        System.out.println(dateAndTimeInNewYork);//2020-04-20T09:25:27.723-04:00[America/New_York]
        ZonedDateTime dateAndTimeInShanghai = ZonedDateTime.of(localDateAndTime, ZoneId.of("Asia/Shanghai"));
        System.out.println(dateAndTimeInShanghai);//2020-04-20T09:25:27.723+08:00[Asia/Shanghai]
    }

    /**
     * 	日期、时间 间隔计算
     * @Description:
     * 	1、日期间隔
     * 	2、时间间隔
     * <br>
     */
    @Test
    public void test7() {
        LocalDate now = LocalDate.now();//2020-07-16
        LocalDate targetDay = LocalDate.of(2010, 10, 21);
        // 计算两个日期之间间隔
        Period p = Period.between(targetDay, now);
        System.out.printf("目标日期距离今天的时间差：%d 年 %d 个月 %d 天\n", p.getYears(), p.getMonths(), p.getDays());//目标日期距离今天的时间差：9 年 8 个月 25 天

        targetDay = LocalDate.of(2020, 4, 13);
        int months = Period.between(targetDay, now).getMonths();
        System.out.println("2020.4.13距今相隔："+months+"个月。");//2020.4.13距今相隔：3个月。

        //计算两个时间之间间隔
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalTime time1 = LocalTime.of(20, 30, 30); // 20:30:30
        //System.out.println(time1);
        LocalTime time2 = time1.plusHours(1); // 21:30:30
        //System.out.println(time2);
        LocalTime time3 = time1.minusMinutes(30); // 20:00:30
        //System.out.println(time3);
        LocalTime time4 = time1.plus(Duration.ofHours(2)); // 22:30:30
        //System.out.println(time4);
        LocalTime time5 = time1.minus(Duration.ofDays(2)); // 20:30:30
        //System.out.println(time5);

        LocalDateTime today = LocalDateTime.now();
        System.out.println("today:"+today);// today:2020-07-16T20:40:15.729
        LocalDateTime bToday = today.minus(Duration.ofDays(2));
        System.out.println("bToday:"+bToday);// bToday:2020-07-14T20:40:15.729

        System.out.println(today.format(formatter)); // 2020-07-16 20:41:12
        System.out.println(bToday.format(formatter));// 2020-07-14 20:41:52

        System.out.println("以秒计的时间差："+ Duration.between(time2, time1).getSeconds());//以秒计的时间差：-3600
        System.out.println("以时计的时间差："+ Duration.between(bToday, today).toHours());//以时计的时间差：48
    }

    /**
     * 	格式化日期
     * @date 2020-07-16 21:10:13
     * @Description:
     * 	1、使用预定义格式器来对日期进行解析
     * 	2、自定义格式器
     * 	3、日期格式化
     * <br>
     */
    @Test
    public void test8() {
        //预定义格式器BASIC_ISO_DATE
        LocalDate localDate = LocalDate.parse("20200716", DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(localDate);//2020-07-16
        System.out.println(localDate.getMonth());//JULY

        //自定义格式器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String date_time = "2020-07-16 21:19:30";
        LocalDate date = LocalDate.parse(date_time, formatter);
        System.out.println(date);//2020-07-16
        LocalTime time = LocalTime.parse(date_time, formatter);
        System.out.println(time);// 21:19:30

        LocalDateTime dateTime = LocalDateTime.parse(date_time, formatter);
        System.out.println(dateTime);// 2020-07-16T21:19:30

        //日期格式化
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now.format(formatter));// 2020-07-16 21:28:55
    }
}
